package io.hellsinger.filesystem.linux.attribute

import io.hellsinger.filesystem.attribute.PathAttribute
import io.hellsinger.filesystem.attribute.PathAttributeWrapper
import io.hellsinger.filesystem.attribute.PathType
import io.hellsinger.filesystem.checkScheme
import io.hellsinger.filesystem.linux.LinuxFileOperationProvider
import io.hellsinger.filesystem.linux.LinuxOperationOptions
import io.hellsinger.filesystem.linux.LinuxOperationOptions.Attributes
import io.hellsinger.filesystem.path.Path
import io.hellsinger.filesystem.path.PathOwner

interface LinuxPathAttribute : PathAttribute {
    val userId: Int
    val groupId: Int
    val mode: Int
}

internal class LinuxPathAttributeImpl(
    override val userId: Int,
    override val groupId: Int,
    override val mode: Int,
    // inode
    override val id: Long,
    override val size: Long,
    lastAccessTimeSeconds: Long,
    lastAccessTimeNanos: Long,
    lastModifiedTimeSeconds: Long,
    lastModifiedTimeNanos: Long,
    creationTimeSeconds: Long,
    creationTimeNanos: Long,
) : PathAttributeWrapper(
        creationTimeNanos,
        creationTimeSeconds,
        lastAccessTimeNanos,
        lastAccessTimeSeconds,
        lastModifiedTimeNanos,
        lastModifiedTimeSeconds,
    ),
    LinuxPathAttribute {
    override val type: PathType = PathType.fromStat(mode and Attributes.S_IFMT)

    override val permission: String = mode.toLinuxEntryModeString()
}

val Path.attributes: PathAttribute
    get() {
        checkScheme(LinuxOperationOptions.SCHEME)

        return LinuxFileOperationProvider.getStatus(bytes) ?: throw Throwable("Path does not exist")
    }

val Path.attributesOrNull: PathAttribute?
    get() {
        checkScheme(LinuxOperationOptions.SCHEME)

        return LinuxFileOperationProvider.getStatus(bytes)
    }

val <P : Path> PathOwner<P>.attributes: PathAttribute
    get() = path.attributes
